/**
 ******************************************************************************
 * @file app_unlock.c
 * @author GX (2524913364@qq.com)
 * @brief   解锁界面
 *          1.有按键反馈，点击按键响应位置会出现皮卡丘的图案
 *   
 * @version 1.0.0 
 * @date 2022-07-10
 * 
 * @copyright Copyright (c) 2022
 * 
 ******************************************************************************
 *----------------------------------------------------------------------------*
 *  Remark         : Description                                              *
 *----------------------------------------------------------------------------*
 *  Change History :                                                          *
 *  <Date>     | <Version> | <Author>       | <Description>                   *
 *----------------------------------------------------------------------------*
 *  2022-07-10 | 1.0.0     | GX             | Create file                     *
 *----------------------------------------------------------------------------*
 *                                                                            *
 ******************************************************************************
 */


/*----------------------------- start of file -------------------------------*/
#include "app_unlock.h"
#include "lcd.h"
#include "touch_screen.h"


static UNLOCK_KEY unlock_GetKey(int x, int y);

/*******************************************************************************
 * 
 *                               锁屏界面相关函数
 * 
*******************************************************************************/

/**
 * @brief 解锁界面
 * 
 * @return true 
 * @return false 
 */
bool unlock_interface(void)
{
  /*------------------------------开启显示屏幕-----------------------------*/
  int fd_lcd;                             /* 打开文件获取文件描述 */
  int *fb_base = NULL;                    /* 映射后显存的地址 */
  struct fb_var_screeninfo vinfo;         /* 显卡设备的可变属性结构体 */
	/* 打开文件 */
	fd_lcd = open(LCD_PATH, O_RDWR);
	if(fd_lcd == -1)
	{
		perror("open lcd");
    return false;
	}
  else
	{
		/* 显存映射 */
		fb_base = mmap(NULL, LCD_BUFF_SIZE*LCD_BLOCK,  PROT_READ|PROT_WRITE,
					MAP_SHARED, fd_lcd, 0);
		if(fb_base == MAP_FAILED) 
		{
			perror("申请显存失败");
      close(fd_lcd);
      return false;
		} 

    if(ioctl(fd_lcd, FBIOGET_VSCREENINFO, &vinfo) != 0)/* 获取可变属性 */
    {
        perror("获取LCD设备可变属性信息失败");
        return false;
    }
  }
  /*------------------------------成功进入-----------------------------*/
  /* 显示字符相关配置----------------------- */
  /* 要先把进来前的字体配置记住，在结束后要设置回来 */
  bool useBack;
  u_int32_t TextColor, BackColor;
  sFONT *fonts;
  /* Font48x64 在"fonts.h"中，一般"lcd.h"已包含 */
  sFONT unlock_fonts = Font48x64;                   /* 本模块要使用的字体大小 */
  u_int32_t unlock_TextColor = UNLOCK_TEXT_COLOR; /* 本模块要使用的字体颜色 */
  fonts = LCD_GetFont();
  LCD_GetColors(&TextColor, &BackColor, &useBack);
  LCD_SetFont(&unlock_fonts); 
  LCD_SetColors(unlock_TextColor, UNLOCK_TEXT_COLOR, false);

  /* 密码相关------------------------------ */
  bool pass = false;  /* 密码正确的标志 */
  char password_buf[UNLOCK_WORD_LEN+1] = {0};
  char dis_password_buf[UNLOCK_WORD_LEN+1] = {0}; /* 用来显示的密码 */
  int pass_pos = 0;   /* 一输入多少位 */
  // printf("buf:%s\n",password_buf);

  UNLOCK_KEY key;  /* 按键 */
  int FB_x, FB_y;   /* 按键反馈图像显示的坐标 */

  /* 更新状态机 */
  Renew_tcState();
  /* 将三块显示区都清屏 */
  LCD_CLEAN(LCD_DISPLAY(fb_base, ++view_block));
  LCD_CLEAN(LCD_DISPLAY(fb_base, ++view_block));
  LCD_CLEAN(LCD_DISPLAY(fb_base, ++view_block));

  lcd_show_bmp(LCD_DISPLAY(fb_base, ++view_block), UNLOCK_WALLPAPER_PATH, 0,  0);
  LCD_SET_DISPLAY(fd_lcd, &vinfo, view_block); 

  TOUCH *tc = malloc(sizeof(TOUCH));
  while(1)
  {
    get_tcState(tc);
    if( tc->response )
    {
      continue;
    }

    switch (tc->state)
    {
    case STATE_SINGLE_CLICK:  /* 单击 */
      /* 响应状态 */
      printf("STATE_SINGLE_CLICK\n");
      response_over();

      /* 获取键值 */
      // printf("(%d,%d)\n", tc->x_last, tc->y_last);
      key = unlock_GetKey(tc->x_last, tc->y_last);
      // printf("key = %d\n", key);

      switch (key)  /* switch(key) "确定用户输入的值" */
      {/* 根据键值确定按键反馈图像显示的坐标 */
      case UNLOCK_0:
        if (pass_pos < UNLOCK_WORD_LEN)
        {
          strcat(password_buf, "0");
          strcat(dis_password_buf, "*");
          pass_pos++;
        }
        
        break;
      
      case UNLOCK_1:
        if (pass_pos < UNLOCK_WORD_LEN)
        {
          strcat(password_buf, "1");
          strcat(dis_password_buf, "*");
          pass_pos++;
        }

        break;

      case UNLOCK_2:
        if (pass_pos < UNLOCK_WORD_LEN)
        {
          strcat(password_buf, "2");
          strcat(dis_password_buf, "*");
          pass_pos++;
        }

        break;

      case UNLOCK_3:
        if (pass_pos < UNLOCK_WORD_LEN)
        {
          strcat(password_buf, "3");
          strcat(dis_password_buf, "*");
          pass_pos++;
        }

        break;

      case UNLOCK_4:
        if (pass_pos < UNLOCK_WORD_LEN)
        {
          strcat(password_buf, "4");
          strcat(dis_password_buf, "*");
          pass_pos++;
        }

        break;

      case UNLOCK_5:
        if (pass_pos < UNLOCK_WORD_LEN)
        {
          strcat(password_buf, "5");
          strcat(dis_password_buf, "*");
          pass_pos++;
        }

        break;

      case UNLOCK_6:
        if (pass_pos < UNLOCK_WORD_LEN)
        {
          strcat(password_buf, "6");
          strcat(dis_password_buf, "*");
          pass_pos++;
        }

        break;

      case UNLOCK_7:
        if (pass_pos < UNLOCK_WORD_LEN)
        {
          strcat(password_buf, "7");
          strcat(dis_password_buf, "*");
          pass_pos++;
        }

        break;

      case UNLOCK_8:
        if (pass_pos < UNLOCK_WORD_LEN)
        {
          strcat(password_buf, "8");
          strcat(dis_password_buf, "*");
          pass_pos++;
        }

        break;
      
      case UNLOCK_9:
        if (pass_pos < UNLOCK_WORD_LEN)
        {
          strcat(password_buf, "9");
          strcat(dis_password_buf, "*");
          pass_pos++;
        }

        break;
        
      case UNLOCK_CONFIRM:
        if (pass_pos == UNLOCK_WORD_LEN)
        {
          printf("cmp...\n");
          if( strcmp(password_buf, UNLOCK_PASSWORD) == 0 )
          {
            printf("passwd true\n");
            pass = true;
          }
          else
          {
            printf("passwd error\n");
            for(char i=0; i<UNLOCK_WORD_LEN; i++)
            {
              password_buf[i] = '\0';
              dis_password_buf[i] = '\0';
            }
            pass_pos = 0;
          }
        }

        break;

      case UNLOCK_BS:
        if (pass_pos > 0)
        {
          password_buf[pass_pos-1] = '\0';
          dis_password_buf[pass_pos-1] = '\0';
          pass_pos--;
        }

        break;
      
      default:

        break;
      }
      // key = UNLOCK_NONE;
      /* end switch(key) "确定用户输入的值" */

      printf("pass_pos\t%d\n", pass_pos);
      printf("passwd:\t%s\n", password_buf);
      printf("dispasswd:\t%s\n", dis_password_buf);

      /* 刷新图像 */
      view_block++;
      LCD_CLEAN(LCD_DISPLAY(fb_base, view_block));
      lcd_show_bmp(LCD_DISPLAY(fb_base, view_block), 
                            UNLOCK_WALLPAPER_PATH, 0,  0);
      DispString_EN(LCD_DISPLAY(fb_base, view_block), 
                    UNLOCK_TEXT_START_X, UNLOCK_TEXT_START_Y, dis_password_buf);
      LCD_SET_DISPLAY(fd_lcd, &vinfo, view_block); 
      
      break;
    
    case STATE_PRESSED:       /* 按住 */
      /* 响应状态 */
      printf("STATE_PRESSED\n");
      // response_over();

      /* 获取键值 */
      // printf("(%d,%d)\n", tc->x, tc->y);
      key = unlock_GetKey(tc->x, tc->y);
      // printf("key = %d\n", key);

      switch (key)  /* switch(key) "确定按键反馈图像显示的位置" */
      {/* 根据键值确定按键反馈图像显示的坐标 */
      case UNLOCK_0:
        FB_x = UNLOCK_0_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_0_Y_START + UNLOCK_FB_DELTA_Y;
        break;
      
      case UNLOCK_1:
        FB_x = UNLOCK_1_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_1_Y_START + UNLOCK_FB_DELTA_Y;
        break;

      case UNLOCK_2:
        FB_x = UNLOCK_2_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_2_Y_START + UNLOCK_FB_DELTA_Y;
        break;

      case UNLOCK_3:
        FB_x = UNLOCK_3_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_3_Y_START + UNLOCK_FB_DELTA_Y;
        break;

      case UNLOCK_4:
        FB_x = UNLOCK_4_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_4_Y_START + UNLOCK_FB_DELTA_Y;
        break;

      case UNLOCK_5:
        FB_x = UNLOCK_5_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_5_Y_START + UNLOCK_FB_DELTA_Y;
        break;

      case UNLOCK_6:
        FB_x = UNLOCK_6_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_6_Y_START + UNLOCK_FB_DELTA_Y;
        break;

      case UNLOCK_7:
        FB_x = UNLOCK_7_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_7_Y_START + UNLOCK_FB_DELTA_Y;
        break;

      case UNLOCK_8:
        FB_x = UNLOCK_8_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_8_Y_START + UNLOCK_FB_DELTA_Y;
        break;
      
      case UNLOCK_9:
        FB_x = UNLOCK_9_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_9_Y_START + UNLOCK_FB_DELTA_Y;
        break;
        
      case UNLOCK_CONFIRM:
        FB_x = UNLOCK_CONFIRM_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_CONFIRM_Y_START + UNLOCK_FB_DELTA_Y;
        break;

      case UNLOCK_BS:
        FB_x = UNLOCK_BS_X_START + UNLOCK_FB_DELTA_X;
        FB_y = UNLOCK_BS_Y_START + UNLOCK_FB_DELTA_Y;
        break;
      
      default:
        FB_x = 400;
        FB_y = 140;
        break;
      }
      /* end switch(key) "确定按键反馈图像显示的位置" */

      /* 刷新图像 */
      view_block++;
      LCD_CLEAN(LCD_DISPLAY(fb_base, view_block));
      lcd_show_bmp(LCD_DISPLAY(fb_base, view_block), UNLOCK_FEEDBACK_PATH, FB_x, FB_y);
      lcd_show_bmp_sticker(LCD_DISPLAY(fb_base, view_block), UNLOCK_WALLPAPER_PATH, 0,  0);
      DispString_EN(LCD_DISPLAY(fb_base, view_block), 
                    UNLOCK_TEXT_START_X, UNLOCK_TEXT_START_Y, dis_password_buf);
      LCD_SET_DISPLAY(fd_lcd, &vinfo, view_block); 
      
      break;

    default:
      printf("other\n");
      response_over();
      view_block++;
      LCD_CLEAN(LCD_DISPLAY(fb_base, view_block));
      lcd_show_bmp(LCD_DISPLAY(fb_base, view_block), 
                            UNLOCK_WALLPAPER_PATH, 0,  0);
      DispString_EN(LCD_DISPLAY(fb_base, view_block), 
                    UNLOCK_TEXT_START_X, UNLOCK_TEXT_START_Y, dis_password_buf);
      LCD_SET_DISPLAY(fd_lcd, &vinfo, view_block); 
      response_over();
      break;
    }
    // usleep(1000);

    /* 密码正确就退出死循环 */
    if( pass )
    {
      break;
    }

  }
  /* while(1) end--------------------------------------------------------- */

  /* 恢复字体设置 */
  LCD_SetFont(fonts); 
  LCD_SetColors(TextColor, BackColor, useBack);

  /* 将三块显示区都清屏 */
  // LCD_CLEAN(LCD_DISPLAY(fb_base, ++view_block));
  // LCD_CLEAN(LCD_DISPLAY(fb_base, ++view_block));
  // LCD_CLEAN(LCD_DISPLAY(fb_base, ++view_block));
  view_block = 0;
  free(tc);
  munmap(fb_base, LCD_BUFF_SIZE*LCD_BLOCK);
  close(fd_lcd);
  
  return true;
}


/**
 * @brief 获取按键键值（辅助函数）
 * 
 * @param x 输入坐标
 * @param y 输入坐标
 * @return UNLOCK_KEY 返回键值
 */
static UNLOCK_KEY unlock_GetKey(int x, int y)
{ 
  /* 确认键 */
  if(( x >= UNLOCK_CONFIRM_X_START ) && ( x <= UNLOCK_CONFIRM_X_END ) &&
      ( y >= UNLOCK_CONFIRM_Y_START ) && ( y <= UNLOCK_CONFIRM_Y_END ))
    {
      return UNLOCK_CONFIRM;
      // printf("confirm\n");
    }
    
  
  /* 返回键 */
  else if(( x >= UNLOCK_BS_X_START ) && ( x <= UNLOCK_BS_X_END ) &&
          ( y >= UNLOCK_BS_Y_START ) && ( y <= UNLOCK_BS_Y_END ))
    {
      return UNLOCK_BS;
      // printf("backspace\n");
    }
    

  /* 0 */
  else if(( x >= UNLOCK_0_X_START ) && ( x <= UNLOCK_0_X_END ) &&
          ( y >= UNLOCK_0_Y_START ) && ( y <= UNLOCK_0_Y_END ))
    {
      return UNLOCK_0;
      // printf("key 0\n");
    }

  /* 1 */
  else if(( x >= UNLOCK_1_X_START ) && ( x <= UNLOCK_1_X_END ) &&
          ( y >= UNLOCK_1_Y_START ) && ( y <= UNLOCK_1_Y_END ))
    {
      return UNLOCK_1;
      // printf("key 1\n");
    }

  /* 2 */
  else if(( x >= UNLOCK_2_X_START ) && ( x <= UNLOCK_2_X_END ) &&
          ( y >= UNLOCK_2_Y_START ) && ( y <= UNLOCK_2_Y_END ))
    {
      return UNLOCK_2;
      // printf("key 2\n");
    }

  /* 3 */
  else if(( x >= UNLOCK_3_X_START ) && ( x <= UNLOCK_3_X_END ) &&
          ( y >= UNLOCK_3_Y_START ) && ( y <= UNLOCK_3_Y_END ))
    {
      return UNLOCK_3;
      // printf("key 3\n"); 
    }
     

  /* 4 */
  else if(( x >= UNLOCK_4_X_START ) && ( x <= UNLOCK_4_X_END ) &&
          ( y >= UNLOCK_4_Y_START ) && ( y <= UNLOCK_4_Y_END ))
    {
      return UNLOCK_4;
      // printf("key 4\n");  
    }
    
    
  /* 5 */
  else if(( x >= UNLOCK_5_X_START ) && ( x <= UNLOCK_5_X_END ) &&
          ( y >= UNLOCK_5_Y_START ) && ( y <= UNLOCK_5_Y_END ))
    {
      return UNLOCK_5;
      // printf("key 5\n");  
    }
    

  /* 6 */
  else if(( x >= UNLOCK_6_X_START ) && ( x <= UNLOCK_6_X_END ) &&
          ( y >= UNLOCK_6_Y_START ) && ( y <= UNLOCK_6_Y_END ))
    {
      return UNLOCK_6;
      // printf("key 6\n"); 
    }
     

  /* 7 */
  else if(( x >= UNLOCK_7_X_START ) && ( x <= UNLOCK_7_X_END ) &&
          ( y >= UNLOCK_7_Y_START ) && ( y <= UNLOCK_7_Y_END ))
    {
      return UNLOCK_7;
      // printf("key 7\n"); 
    } 
    

  /* 8 */
  else if(( x >= UNLOCK_8_X_START ) && ( x <= UNLOCK_8_X_END ) &&
          ( y >= UNLOCK_8_Y_START ) && ( y <= UNLOCK_8_Y_END ))
    {
      return UNLOCK_8;
      // printf("key 8\n"); 
    }
     

  /* 9 */
  else if(( x >= UNLOCK_9_X_START ) && ( x <= UNLOCK_9_X_END ) &&
          ( y >= UNLOCK_9_Y_START ) && ( y <= UNLOCK_9_Y_END ))
    {
      return UNLOCK_9;
      // printf("key 9\n");
    }
    
  return UNLOCK_NONE;
}




/*------------------------------ end of file --------------------------------*/

